﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Warensoft.Unity.Communication.Client.Contracts
{
    public class WarensoftMessage : MessageBase
    {
        public WarensoftMessage()
        { }
        public WarensoftMessage(byte[] buffer)
            : base(buffer)
        { }
        public string CommandName { get; set; }
        public override byte[] ToArray()
        {
            if (string.IsNullOrEmpty(this.CommandName))
            {
                throw new Exception("协议名不能为空！");
            }
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write(this.CommandName);
            foreach (var item in this.Properties)
            {

                bw.Write(item.Key);
                if (item.Value is byte)
                {
                    bw.Write((byte)DataTypes.BYTE);
                    bw.Write((byte)item.Value);
                    continue;
                }
                if (item.Value is bool)
                {
                    bw.Write((byte)DataTypes.BOOL);
                    bw.Write((bool)item.Value);
                    continue;
                }
                if (item.Value is short)
                {
                    bw.Write((byte)DataTypes.SHORT);
                    bw.Write((short)item.Value);
                    continue;
                }
                if (item.Value is int)
                {
                    bw.Write((byte)DataTypes.INT);
                    bw.Write((int)item.Value);
                    continue;
                }
                if (item.Value is long)
                {
                    bw.Write((byte)DataTypes.LONG);
                    bw.Write((long)item.Value);
                    continue;
                }
                if (item.Value is float)
                {
                    bw.Write((byte)DataTypes.FLOAT);
                    bw.Write((float)item.Value);
                    continue;
                }
                if (item.Value is double)
                {
                    bw.Write((byte)DataTypes.DOUBLE);
                    bw.Write((double)item.Value);
                    continue;
                }
                if (item.Value is string)
                {
                    bw.Write((byte)DataTypes.STRING);
                    bw.Write(item.Value.ToString());
                    continue;
                }

            }
            var buffer = ms.ToArray();
            ms.Close();
            bw.Close();
            var lengthBuffer = BitConverter.GetBytes((short)buffer.Length);
            var result = lengthBuffer.Concat(buffer).ToArray();
            return result;
        }

        protected override void FillProperties(byte[] buffer)
        {
            using (MemoryStream ms = new MemoryStream(buffer))
            {
                ms.Position = 0;
                using (BinaryReader br = new BinaryReader(ms))
                {


                    this.CommandName = br.ReadString();
                    while (ms.Position != ms.Length )
                    {
                        string propertyName = br.ReadString();
                        var type = (DataTypes)br.ReadByte();
                        switch (type)
                        {
                            case DataTypes.BYTE:
                                this.Properties.Add(propertyName, br.ReadByte());

                                break;
                            case DataTypes.BOOL:
                                this.Properties.Add(propertyName, br.ReadBoolean());

                                break;
                            case DataTypes.SHORT:
                                this.Properties.Add(propertyName, br.ReadInt16());

                                break;
                            case DataTypes.INT:
                                this.Properties.Add(propertyName, br.ReadInt32());

                                break;
                            case DataTypes.LONG:
                                this.Properties.Add(propertyName, br.ReadInt64());

                                break;
                            case DataTypes.FLOAT:
                                this.Properties.Add(propertyName, br.ReadSingle());

                                break;
                            case DataTypes.DOUBLE:
                                this.Properties.Add(propertyName, br.ReadDouble());

                                break;
                            case DataTypes.STRING:
                                var value = br.ReadString();
                                this.Properties.Add(propertyName, value);

                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
}
